package org.kernely.security.ui.group.mgmt;

import org.hibernate.exception.ConstraintViolationException;
import org.kernely.security.dao.GroupDAO;
import org.kernely.security.persistence.Group;
import org.kernely.security.persistence.Role;
import org.kernely.security.ui.SecurityUIBundle;
import org.kernely.ui.mvp.KernelyPresenter;
import org.kernely.ui.utils.KernelyNotification;

import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.terminal.UserError;
import com.vaadin.ui.Button;
import com.vaadin.ui.Layout;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Window.Notification;

public class GroupManagementWindowPresenter extends KernelyPresenter<GroupManagementWindowView>{

	/**
	 * In edit mode, the group to edit
	 */
	private Group group;
	
	private boolean editMode = false;
	
	/**
	 * Group creation/edition view and presenter associated to this window
	 */
	private AddEditGroupManagementView gmv;
	private AddEditGroupManagementPresenter gmp;
	
	/**
	 * Group's roles edition view and presenter associated to this window
	 */
	private EditGroupRoleView egrv;
	private EditGroupRolePresenter egrp;
	
	/**
	 * Default constructor (Creation Mode)
	 */
	public GroupManagementWindowPresenter(){}
	
	/**
	 * Constructor for the edition mode
	 * @param group : the group to edit
	 */
	public GroupManagementWindowPresenter(Group group){
		this.group = group;
		this.editMode = true;
	}
	
	/**
	 * @see org.kernely.ui.mvp.IKernelyPresenter#bind()
	 */
	@Override
	public void bind() {
		// Add Mode
		if(group == null){
			gmp = new AddEditGroupManagementPresenter();
			egrp = new EditGroupRolePresenter();
		}
		// edit Mode
		else{
			gmp = new AddEditGroupManagementPresenter(group);
			egrp = new EditGroupRolePresenter(group);
		}
		gmv = new AddEditGroupManagementView();
		egrv = new EditGroupRoleView();
		gmp.setView(gmv);
		egrp.setView(egrv);
		
		view.getTabsheet().addTab((Layout)gmp.getView(), "Informations", null);
		view.getTabsheet().addTab((Layout)egrp.getView(), "Roles", null);
		
		// Add a listener to the save button
		this.view.getSaveButton().addListener(new Button.ClickListener() {
			/**
			 * The Serial Version ID
			 */
			private static final long serialVersionUID = -515612812186312L;

			/**
			 * Action when the button is clicked
			 */
			public void buttonClick(ClickEvent event) {
				if(!SecurityUIBundle.getSecurityService().getCurrentUser().hasOneOf(Role.ROLE_ADMINISTRATOR)){
					view.getWindow().getParent().showNotification("Error", "You are not an administrator !", Notification.TYPE_ERROR_MESSAGE);
				}
				else{
					save();
				}
			}
		});

		// Add a listener to the cancel button
		this.view.getCancelButton().addListener(new Button.ClickListener() {
			/**
			 * The Serial Version ID
			 */
			private static final long serialVersionUID = -515612812186312L;

			/**
			 * Action when the button is clicked
			 */
			public void buttonClick(ClickEvent event) {
				// Close the window
				Window win = (Window)view.getParent();
				win.getParent().removeWindow(win);
			}
		});
	}
	
	/**
	 * Save the group with all informations and roles into the database
	 */
	private void save(){
		try{
			// Check all fields
			gmv.getName().validate();

			Group g = new Group();
			GroupDAO gdao = new GroupDAO();

			g.setName((String)gmv.getName().getValue());
			g.setUsers(gmp.getGroupUsers());
			
			g.setRoles(egrp.getGroupRoles());
			// Save the group, or update in edit mode
			if(editMode){
				g.setId(group.getId());
				gdao.updateGroup(g);
			}
			else{
				gdao.saveGroup(g);	
			}
			
			//Send an event to refresh the background page.
			SecurityUIBundle.getEventBus().broadcastEvent(new ManagementGroupEvent(this));

			// Inform the user
			KernelyNotification notification;
			if (editMode){
				notification = new KernelyNotification("Group " + g.getName() + " successfully updated.",KernelyNotification.INFO_ICON);
			}
			else {
				notification = new KernelyNotification("Group " + g.getName() + " successfully created.",KernelyNotification.INFO_ICON);
			}
			view.getWindow().getParent().showNotification(notification);

			// Close the window when operation succeeded
			Window win = (Window)view.getParent();
			win.getParent().removeWindow(win);
		}
		catch (InvalidValueException e){
			//Log the failure on screen, to give feedback to the user
			KernelyNotification notification = new KernelyNotification(e.getMessage(),KernelyNotification.ERROR_ICON);
			view.getWindow().showNotification(notification);
			// Display failure on the concerned component
			gmv.getName().setComponentError(new UserError("Nam can't be empty."));
		}
		catch (ConstraintViolationException cve){
			view.getWindow().showNotification(new KernelyNotification("A group with this name already exists.", KernelyNotification.ERROR_ICON));
			// Display failure on the concerned component
			gmv.getName().setComponentError(new UserError("A group with this name already exists."));
		}
	}
}
